Was ist der beste Weg, um zu überprüfen, ob ein String eine ganze Zahl in Java darstellt?
Frage
ich normalerweise folgendes Idiom verwenden, um zu überprüfen, ob ein String kann auf eine ganze Zahl umgewandelt werden.
public boolean isInteger( String input ) {
try {
Integer.parseInt( input );
return true;
}
catch( Exception e ) {
return false;
}
}
Ist es nur mich, oder hat dies ein wenig hackish scheinen? Was ist ein besserer Weg?
Siehe meine Antwort (mit Benchmarks, basierend auf dem früher beantworten von CodingWithSpike ), um zu sehen, warum ich meine Position umgekehrt haben und akzeptierte Antwort Jonas Klemming der für dieses Problem. Ich denke, das Original-Code wird von den meisten Menschen verwendet werden, da es schneller zu implementieren ist, und besser verwaltbar, aber es ist um Größenordnungen langsamer als nicht-ganzzahligen Daten vorgesehen ist.
Lösung
Wenn Sie nicht besorgt mit potentiellen Überlaufproblemen wird diese Funktion etwa 20-30 mal schneller ab als Integer.parseInt()
verwendet wird.
public static boolean isInteger(String str) {
if (str == null) {
return false;
}
int length = str.length();
if (length == 0) {
return false;
}
int i = 0;
if (str.charAt(0) == '-') {
if (length == 1) {
return false;
}
i = 1;
}
for (; i < length; i++) {
char c = str.charAt(i);
if (c < '0' || c > '9') {
return false;
}
}
return true;
}
Andere Tipps
Sie haben es, aber Sie sollten nur NumberFormatException
fangen.
Da gibt es die Möglichkeit, dass die Menschen immer noch hier besuchen und werden gegen Regex nach dem Benchmarks voreingenommen sein ... Also ich werde eine aktualisierte Version der Benchmark geben, mit einer kompilierten Version des Regex. Welche zu dem bisherigen Benchmarks gegenüber, dies zeigt Regex Lösung tatsächlich eine konstant gute Leistung hat.
Kopiert von Bill the Lizard und aktualisiert mit kompilierte Version:
private final Pattern pattern = Pattern.compile("^-?\\d+$");
public void runTests() {
String big_int = "1234567890";
String non_int = "1234XY7890";
long startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByException(big_int);
long endTime = System.currentTimeMillis();
System.out.print("ByException - integer data: ");
System.out.println(endTime - startTime);
startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByException(non_int);
endTime = System.currentTimeMillis();
System.out.print("ByException - non-integer data: ");
System.out.println(endTime - startTime);
startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByRegex(big_int);
endTime = System.currentTimeMillis();
System.out.print("\nByRegex - integer data: ");
System.out.println(endTime - startTime);
startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByRegex(non_int);
endTime = System.currentTimeMillis();
System.out.print("ByRegex - non-integer data: ");
System.out.println(endTime - startTime);
startTime = System.currentTimeMillis();
for (int i = 0; i < 100000; i++)
IsInt_ByCompiledRegex(big_int);
endTime = System.currentTimeMillis();
System.out.print("\nByCompiledRegex - integer data: ");
System.out.println(endTime - startTime);
startTime = System.currentTimeMillis();
for (int i = 0; i < 100000; i++)
IsInt_ByCompiledRegex(non_int);
endTime = System.currentTimeMillis();
System.out.print("ByCompiledRegex - non-integer data: ");
System.out.println(endTime - startTime);
startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByJonas(big_int);
endTime = System.currentTimeMillis();
System.out.print("\nByJonas - integer data: ");
System.out.println(endTime - startTime);
startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByJonas(non_int);
endTime = System.currentTimeMillis();
System.out.print("ByJonas - non-integer data: ");
System.out.println(endTime - startTime);
}
private boolean IsInt_ByException(String str)
{
try
{
Integer.parseInt(str);
return true;
}
catch(NumberFormatException nfe)
{
return false;
}
}
private boolean IsInt_ByRegex(String str)
{
return str.matches("^-?\\d+$");
}
private boolean IsInt_ByCompiledRegex(String str) {
return pattern.matcher(str).find();
}
public boolean IsInt_ByJonas(String str)
{
if (str == null) {
return false;
}
int length = str.length();
if (length == 0) {
return false;
}
int i = 0;
if (str.charAt(0) == '-') {
if (length == 1) {
return false;
}
i = 1;
}
for (; i < length; i++) {
char c = str.charAt(i);
if (c <= '/' || c >= ':') {
return false;
}
}
return true;
}
Ergebnisse:
ByException - integer data: 45
ByException - non-integer data: 465
ByRegex - integer data: 272
ByRegex - non-integer data: 131
ByCompiledRegex - integer data: 45
ByCompiledRegex - non-integer data: 26
ByJonas - integer data: 8
ByJonas - non-integer data: 2
Hat eine schnelle Benchmark. Ausnahmen sind nicht wirklich, dass expensivve, es sei denn, Sie mehrere Methoden und die JVM zu tun hat, eine Menge Arbeit zu bekommen, die Ausführung Stapel anstelle beginnen knallen zurück. Wenn in der gleichen Methode zu bleiben, sind sie nicht schlecht Darsteller.
public void RunTests()
{
String str = "1234567890";
long startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByException(str);
long endTime = System.currentTimeMillis();
System.out.print("ByException: ");
System.out.println(endTime - startTime);
startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByRegex(str);
endTime = System.currentTimeMillis();
System.out.print("ByRegex: ");
System.out.println(endTime - startTime);
startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByJonas(str);
endTime = System.currentTimeMillis();
System.out.print("ByJonas: ");
System.out.println(endTime - startTime);
}
private boolean IsInt_ByException(String str)
{
try
{
Integer.parseInt(str);
return true;
}
catch(NumberFormatException nfe)
{
return false;
}
}
private boolean IsInt_ByRegex(String str)
{
return str.matches("^-?\\d+$");
}
public boolean IsInt_ByJonas(String str)
{
if (str == null) {
return false;
}
int length = str.length();
if (length == 0) {
return false;
}
int i = 0;
if (str.charAt(0) == '-') {
if (length == 1) {
return false;
}
i = 1;
}
for (; i < length; i++) {
char c = str.charAt(i);
if (c <= '/' || c >= ':') {
return false;
}
}
return true;
}
Ausgabe:
ByException: 31
ByRegex: 453 (Anmerkung: Wiederzusammenstellung der Muster jedes Mal)
ByJonas: 16
Ich bin damit einverstanden, dass Jonas K-Lösung auch die robusteste ist. Sieht aus wie er gewinnt:)
org.apache.commons.lang.StringUtils.isNumeric
obwohl Java Standard lib wirklich vermisst solche Nutzenfunktionen
Ich denke, dass Apache Commons ist ein "must have" für jeden Java-Programmierer
zu schlecht ist sie nicht portiert Java5 noch
Es hängt zum Teil davon ab, was Sie unter „kann auf eine ganze Zahl umgewandelt werden“.
Wenn Sie meinen, „kann in einen int in Java umgewandelt werden“, dann ist die Antwort von Jonas ist ein guter Anfang, ist aber nicht ganz den Job zu beenden. Es wäre 999999999999999999999999999999 zum Beispiel passieren. Ich würde den normalen try / catch Anruf von Ihrer eigenen Frage am Ende des Verfahrens hinzuzufügen.
Die Zeichen-für-Zeichen-Kontrollen effizient ablehnen „keine ganze Zahl ist auf all“ Fälle, so dass „es ist eine ganze Zahl, aber Java kann nicht damit umgehen“ Fälle von der langsameren Ausnahme Strecke gefangen werden. Sie könnte tun, um dieses Bit von Hand zu, aber es wäre ein Los komplizierter sein.
Nur ein Kommentar über regexp. Jedes Beispiel vorgesehen ist hier falsch !. Wenn Sie möchten, regexp verwenden, vergessen Sie nicht, dass das Muster eine Menge Zeit in Anspruch nehmen zu kompilieren. Dies:
str.matches("^-?\\d+$")
und auch dies:
Pattern.matches("-?\\d+", input);
Ursachen kompilieren des Musters in jedem Methodenaufruf. Gewöhnungs es richtig folgen:
import java.util.regex.Pattern;
/**
* @author Rastislav Komara
*/
public class NaturalNumberChecker {
public static final Pattern PATTERN = Pattern.compile("^\\d+$");
boolean isNaturalNumber(CharSequence input) {
return input != null && PATTERN.matcher(input).matches();
}
}
kopierte ich den Code aus rally25rs beantworten und fügte einige Tests für nicht-ganzzahligen Daten. Die Ergebnisse sind unbestreitbar zugunsten der Methode von Jonas Klemming geschrieben. Die Ergebnisse für die Exception-Methode, die ich ursprünglich geschrieben sind ziemlich gut, wenn Sie Integer-Daten haben, aber sie sind das Schlimmste, wenn Sie dies nicht tun, während die Ergebnisse für die RegEx-Lösung (dass ich eine Menge Leute verwenden wette) waren konsequent schlecht. Siehe Felipe Antwort für eine kompilierte Regex Beispiel, das viel schneller ist.
public void runTests()
{
String big_int = "1234567890";
String non_int = "1234XY7890";
long startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByException(big_int);
long endTime = System.currentTimeMillis();
System.out.print("ByException - integer data: ");
System.out.println(endTime - startTime);
startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByException(non_int);
endTime = System.currentTimeMillis();
System.out.print("ByException - non-integer data: ");
System.out.println(endTime - startTime);
startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByRegex(big_int);
endTime = System.currentTimeMillis();
System.out.print("\nByRegex - integer data: ");
System.out.println(endTime - startTime);
startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByRegex(non_int);
endTime = System.currentTimeMillis();
System.out.print("ByRegex - non-integer data: ");
System.out.println(endTime - startTime);
startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByJonas(big_int);
endTime = System.currentTimeMillis();
System.out.print("\nByJonas - integer data: ");
System.out.println(endTime - startTime);
startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByJonas(non_int);
endTime = System.currentTimeMillis();
System.out.print("ByJonas - non-integer data: ");
System.out.println(endTime - startTime);
}
private boolean IsInt_ByException(String str)
{
try
{
Integer.parseInt(str);
return true;
}
catch(NumberFormatException nfe)
{
return false;
}
}
private boolean IsInt_ByRegex(String str)
{
return str.matches("^-?\\d+$");
}
public boolean IsInt_ByJonas(String str)
{
if (str == null) {
return false;
}
int length = str.length();
if (length == 0) {
return false;
}
int i = 0;
if (str.charAt(0) == '-') {
if (length == 1) {
return false;
}
i = 1;
}
for (; i < length; i++) {
char c = str.charAt(i);
if (c <= '/' || c >= ':') {
return false;
}
}
return true;
}
Ergebnisse:
ByException - integer data: 47
ByException - non-integer data: 547
ByRegex - integer data: 390
ByRegex - non-integer data: 313
ByJonas - integer data: 0
ByJonas - non-integer data: 16
Es gibt Guave Version:
import com.google.common.primitives.Ints;
Integer intValue = Ints.tryParse(stringValue);
Es wird null zurück, anstatt eine Ausnahme zu werfen, wenn es Zeichenfolge analysieren ausfällt.
Dies ist kürzer, aber kürzer ist nicht unbedingt besser (und es wird nicht ganzzahlige Werte fangen, die außerhalb des Bereichs liegen, wie in danatel Kommentar darauf hingewiesen):
input.matches("^-?\\d+$");
Persönlich, da die Umsetzung squirrelled in einem Hilfsmethode entfernt und Richtigkeit übertrumpft Länge, würde ich mit etwas gehen wie, was Sie haben (minus fangen die Basis Exception
Klasse statt NumberFormatException
).
Sie können die Streichhölzer Methode der String-Klasse verwenden. Die [0-9] für alle Werte, es sein kann, das heißt, es + mindestens ein Zeichen lang sein muß, und das * bedeutet, es kann null oder mehr Zeichen lang sein.
boolean isNumeric = yourString.matches("[0-9]+"); // 1 or more characters long, numbers only
boolean isNumeric = yourString.matches("[0-9]*"); // 0 or more characters long, numbers only
Dies ist eine Java 8 Variation von Jonas Klemming Antwort:
public static boolean isInteger(String str) {
return str != null && str.length() > 0 &&
IntStream.range(0, str.length()).allMatch(i -> i == 0 && (str.charAt(i) == '-' || str.charAt(i) == '+')
|| Character.isDigit(str.charAt(i)));
}
Testcode:
public static void main(String[] args) throws NoSuchAlgorithmException, UnsupportedEncodingException {
Arrays.asList("1231231", "-1232312312", "+12313123131", "qwqe123123211", "2", "0000000001111", "", "123-", "++123",
"123-23", null, "+-123").forEach(s -> {
System.out.printf("%15s %s%n", s, isInteger(s));
});
}
Die Ergebnisse des Tests Code:
1231231 true
-1232312312 true
+12313123131 true
qwqe123123211 false
2 true
0000000001111 true
false
123- false
++123 false
123-23 false
null false
+-123 false
Wenn Ihr String Array reine Ganze Zahlen enthält und Streicher, Code unten sollte funktionieren. Sie haben nur auf den ersten Zeichen zu suchen. z.B. [ "4", "44", "ABC", "77", "bond"]
if (Character.isDigit(string.charAt(0))) {
//Do something with int
}
Sie können auch die Scanner Klasse, und verwenden Sie hasNextInt () - und dies ermöglicht es Ihnen, für andere Arten zu testen, auch, wie Schwimmer, usw.
.Wie wäre:
return Pattern.matches("-?\\d+", input);
Sie haben soeben überprüfen Number : -
String value="123";
try
{
int s=Integer.parseInt(any_int_val);
// do something when integer values comes
}
catch(NumberFormatException nfe)
{
// do something when string values comes
}
Sie müssen wahrscheinlich den Anwendungsfall in Rechnung tragen auch:
Wenn die meiste Zeit Sie Zahlen erwarten gültig ist, dann die Ausnahme abfangen nur eine Performance-Overhead zu verursachen, wenn Sie versuchen, ungültige Nummern zu konvertieren. Während einige isInteger()
Methode aufrufen und dann konvertieren mit Integer.parseInt()
wird immer verursachen eine Performance-Overhead für gültige Zahlen -. Die Saiten werden zweimal analysiert, einmal durch die Prüfung und einmal durch die Umwandlung
Dies ist eine Modifikation von Jonas ‘Code, der die Zeichenfolge überprüft, ob sich innerhalb der Reichweite ist, in eine ganze Zahl gegossen werden.
public static boolean isInteger(String str) {
if (str == null) {
return false;
}
int length = str.length();
int i = 0;
// set the length and value for highest positive int or lowest negative int
int maxlength = 10;
String maxnum = String.valueOf(Integer.MAX_VALUE);
if (str.charAt(0) == '-') {
maxlength = 11;
i = 1;
maxnum = String.valueOf(Integer.MIN_VALUE);
}
// verify digit length does not exceed int range
if (length > maxlength) {
return false;
}
// verify that all characters are numbers
if (maxlength == 11 && length == 1) {
return false;
}
for (int num = i; num < length; num++) {
char c = str.charAt(num);
if (c < '0' || c > '9') {
return false;
}
}
// verify that number value is within int range
if (length == maxlength) {
for (; i < length; i++) {
if (str.charAt(i) < maxnum.charAt(i)) {
return true;
}
else if (str.charAt(i) > maxnum.charAt(i)) {
return false;
}
}
}
return true;
}
Wenn Sie die Android API verwenden, können Sie verwenden:
TextUtils.isDigitsOnly(str);
Eine weitere Option:
private boolean isNumber(String s) {
boolean isNumber = true;
for (char c : s.toCharArray()) {
isNumber = isNumber && Character.isDigit(c);
}
return isNumber;
}
Wenn Sie überprüfen wollen, ob die Zeichenfolge eine ganze Zahl darstellt, die in einem int-Typ passt, habe ich eine kleine Änderung auf die Antwort jonas, so dass Zeichenketten, die ganze Zahlen größer als Integer.MAX_VALUE repräsentieren oder kleiner als Integer.MIN_VALUE, wird nun return false. Zum Beispiel: „3147483647“ wird falsch zurück, weil 3147483647 größer als 2147483647 ist, und ebenso „-2147483649“ auch falsch zurück, weil -2147483649 kleiner als -2147483648 ist
.public static boolean isInt(String s) {
if(s == null) {
return false;
}
s = s.trim(); //Don't get tricked by whitespaces.
int len = s.length();
if(len == 0) {
return false;
}
//The bottom limit of an int is -2147483648 which is 11 chars long.
//[note that the upper limit (2147483647) is only 10 chars long]
//Thus any string with more than 11 chars, even if represents a valid integer,
//it won't fit in an int.
if(len > 11) {
return false;
}
char c = s.charAt(0);
int i = 0;
//I don't mind the plus sign, so "+13" will return true.
if(c == '-' || c == '+') {
//A single "+" or "-" is not a valid integer.
if(len == 1) {
return false;
}
i = 1;
}
//Check if all chars are digits
for(; i < len; i++) {
c = s.charAt(i);
if(c < '0' || c > '9') {
return false;
}
}
//If we reached this point then we know for sure that the string has at
//most 11 chars and that they're all digits (the first one might be a '+'
// or '-' thought).
//Now we just need to check, for 10 and 11 chars long strings, if the numbers
//represented by the them don't surpass the limits.
c = s.charAt(0);
char l;
String limit;
if(len == 10 && c != '-' && c != '+') {
limit = "2147483647";
//Now we are going to compare each char of the string with the char in
//the limit string that has the same index, so if the string is "ABC" and
//the limit string is "DEF" then we are gonna compare A to D, B to E and so on.
//c is the current string's char and l is the corresponding limit's char
//Note that the loop only continues if c == l. Now imagine that our string
//is "2150000000", 2 == 2 (next), 1 == 1 (next), 5 > 4 as you can see,
//because 5 > 4 we can guarantee that the string will represent a bigger integer.
//Similarly, if our string was "2139999999", when we find out that 3 < 4,
//we can also guarantee that the integer represented will fit in an int.
for(i = 0; i < len; i++) {
c = s.charAt(i);
l = limit.charAt(i);
if(c > l) {
return false;
}
if(c < l) {
return true;
}
}
}
c = s.charAt(0);
if(len == 11) {
//If the first char is neither '+' nor '-' then 11 digits represent a
//bigger integer than 2147483647 (10 digits).
if(c != '+' && c != '-') {
return false;
}
limit = (c == '-') ? "-2147483648" : "+2147483647";
//Here we're applying the same logic that we applied in the previous case
//ignoring the first char.
for(i = 1; i < len; i++) {
c = s.charAt(i);
l = limit.charAt(i);
if(c > l) {
return false;
}
if(c < l) {
return true;
}
}
}
//The string passed all tests, so it must represent a number that fits
//in an int...
return true;
}
is_number = true;
try {
Integer.parseInt(mystr)
} catch (NumberFormatException e) {
is_number = false;
}
Was Sie getan haben funktioniert, aber Sie sollten wahrscheinlich nicht immer auf diese Weise überprüfen. Werfen Ausnahmen sollten für „außergewöhnliche“ Situationen reserviert werden (vielleicht, dass in Ihrem Fall paßt, obwohl), und sind sehr teuer in Bezug auf Leistung.
Number number;
try {
number = NumberFormat.getInstance().parse("123");
} catch (ParseException e) {
//not a number - do recovery.
e.printStackTrace();
}
//use number
Dies würde nur für positive ganze Zahlen arbeiten.
public static boolean isInt(String str) {
if (str != null && str.length() != 0) {
for (int i = 0; i < str.length(); i++) {
if (!Character.isDigit(str.charAt(i))) return false;
}
}
return true;
}
Das funktioniert für mich. Einfach zu erkennen, ob ein String eine primitive oder eine Zahl ist.
private boolean isPrimitive(String value){
boolean status=true;
if(value.length()<1)
return false;
for(int i = 0;i<value.length();i++){
char c=value.charAt(i);
if(Character.isDigit(c) || c=='.'){
}else{
status=false;
break;
}
}
return status;
}
Um zu überprüfen, für alle Zeichen int, können Sie einfach doppelt negativ verwenden.
if (! SearchString.matches ( "[^ 0-9] + $")) ...
[^ 0-9] + $ Kontrollen, um zu sehen, ob es irgendwelche Zeichen, die nicht integer sind, so dass der Test schlägt fehl, wenn es wahr ist. Einfach nicht und Sie erhalten bei Erfolg true.
Im Mai dieses Jahres finden hilfreich:
public static boolean isInteger(String self) {
try {
Integer.valueOf(self.trim());
return true;
} catch (NumberFormatException nfe) {
return false;
}
}
Ich glaube, dass es Null-Risiko in eine Ausnahme ausgeführt wird, weil, wie Sie unten sehen Sie können immer sicher int
analysieren String
und nicht anders herum.
So:
-
Sie prüfen , wenn jeder Schlitz von Zeichen in der Zeichenfolge mindestens Spiele eines des Zeichens { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"} .
if(aString.substring(j, j+1).equals(String.valueOf(i)))
-
Sie Summe alle Zeiten, die Sie in den Schlitzen die oben gestoßen Zeichen.
digits++;
-
Und schließlich Sie überprüfen , wenn die Zeiten, die Sie ganze Zahlen auftreten als Zeichen gleich mit der Länge des Strings.
if(digits == aString.length())
Und in der Praxis haben wir:
String aString = "1234224245";
int digits = 0;//count how many digits you encountered
for(int j=0;j<aString.length();j++){
for(int i=0;i<=9;i++){
if(aString.substring(j, j+1).equals(String.valueOf(i)))
digits++;
}
}
if(digits == aString.length()){
System.out.println("It's an integer!!");
}
else{
System.out.println("It's not an integer!!");
}
String anotherString = "1234f22a4245";
int anotherDigits = 0;//count how many digits you encountered
for(int j=0;j<anotherString.length();j++){
for(int i=0;i<=9;i++){
if(anotherString.substring(j, j+1).equals(String.valueOf(i)))
anotherDigits++;
}
}
if(anotherDigits == anotherString.length()){
System.out.println("It's an integer!!");
}
else{
System.out.println("It's not an integer!!");
}
Und die Ergebnisse sind:
Es ist eine ganze Zahl !!
Es ist nicht eine ganze Zahl !!
In ähnlicher Weise können Sie überprüfen, ob ein String
ein float
oder ein double
aber in diesen Fällen müssen Sie stoßen nur einer. (dot) im String und natürlich überprüfen, ob digits == (aString.length()-1)
Auch hier gibt es Null-Risiko in eine Parsing Ausnahme läuft hier, aber wenn Sie auf das Parsen eine Zeichenfolge planen, dass es bekannt ist, dass eine Zahl enthält (sagen wir mal int Datentyp) müssen Sie zuerst überprüfen, ob es passt in den Datentyp. Andernfalls müssen Sie ihn werfen.
Ich hoffe, ich half